 /*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 /**
 * Project  : EasyAvatar-Lib
 * Package  : net.solosky.easyavatar.api.impl
 * File     : FetionSocialProvider.java
 * Author   : solosky < solosky772@qq.com >
 * Created  : 2011-10-24
 * License  : Apache License 2.0 
 */
package net.solosky.easyavatar.api.impl;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.solosky.easyavatar.api.ApiException;
import net.solosky.easyavatar.api.Avatar;
import net.solosky.easyavatar.api.Avatar.Scale;
import net.solosky.easyavatar.api.ErrorCode;
import net.solosky.easyavatar.api.Friend;
import net.solosky.easyavatar.api.FriendList;
import net.solosky.easyavatar.api.Group;
import net.solosky.easyavatar.api.http.HttpRequest;
import net.solosky.easyavatar.api.http.HttpResponse;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * 飞信好友提供者
 * 利用WebFetion的协议获取飞信好友和头像
 *
 * @author solosky <solosky772@qq.com>
 *
 */
public class FetionFriendProvider extends AbstractWebFriendProvider{
	private static final String URL_INIT    = "http://feixin.10086.cn/account/login?returnurl=http%3a%2f%2fmy.feixin.10086.cn%2fbuddy%2findex";
	private static final String URL_LOGIN   = "http://feixin.10086.cn/account/login/?returnurl=http%3a%2f%2fmy.feixin.10086.cn%2f"; 
	private static final String URL_CAPTCHA = "http://feixin.10086.cn/account/ValidateNumberPicture.aspx?d=%f";
	private static final String URL_GROUPS  = "http://my.feixin.10086.cn/buddy/BuddyGroupName";
	private static final String URL_FRIENDS = "http://my.feixin.10086.cn/buddy/BuddyList";
	private static final String URL_MAYKNOWNS      = "http://my.feixin.10086.cn/buddy/recommendfriendajax/";
	private static final String URL_FRIEND_AVATAR  = "http://my.feixin.10086.cn/buddy/buddyportrait?uid=%s&&eid=%s";
	private static final String URL_MY_AVATAR      = "http://my.feixin.10086.cn/httphandler/getuserprotrait.ashx";
	private static final String URL_MY_INFO        = "http://my.feixin.10086.cn/user/modify";
	/**解析飞信号和昵称的正则，飞信没有提供获取个人信息的接口*/
	private static final String PT_MY_ID      = "飞信号：</strong><p>(.*?)</p></li>";
	private static final String PT_MY_NICK    = "<a id=\"m_nickname\" .*?>(.*?)</a>";
	
	private static final String ERR_WRONG_CAPTCHA = "error.show('<i></i>您输入的验证码有误，请重新输入。');\r\n</script>";
	private static final String ERR_WRONG_PASSWORD = "error.show('<i></i>密码输入有误，请重新输入。');\r\n</script>";
	private static final String REGXP_GROUP = "<a.*?onclick=\"GroupListViewAjax\\((.*?),0\\);\" regid=\".*?\">(.+?) \\[(\\d+)\\]</a>";
	public FetionFriendProvider(){
	}
	@Override
	public void init() throws ApiException, IOException {
		HttpRequest req = createHttpRequest(URL_INIT, "GET");
		executeHttpRequest(req);
	}

	@Override
	public void signIn(String username, String password, String captcha)
			throws ApiException, IOException {
		//飞信强制需要验证码
		if(captcha==null)
			throw new ApiException(ErrorCode.NEED_CAPTCHA, null);
		
		//尝试登陆
		HttpRequest req = createHttpRequest(URL_LOGIN, "POST");
		req.addPostValue("username", username);
		req.addPostValue("password", password);
		req.addPostValue("save", "");
		req.addPostValue("verificationcode", captcha);
		req.addPostValue("Submit", "");
		req.addPostValue("offon", "1");
		
		HttpResponse res = executeHttpRequest(req);
		
		if(res.getResponseCode()!=HttpResponse.HTTP_MOVED_TEMP){
			String body = res.getResponseString();
			if(body.indexOf(ERR_WRONG_CAPTCHA)!=-1){
				throw new ApiException(ErrorCode.WRONG_CAPTCHA, null);
			}else if(body.indexOf(ERR_WRONG_PASSWORD)!=-1){
				throw new ApiException(ErrorCode.WRONG_PASSWORD, null);
			}else{
				throw new ApiException(ErrorCode.INVALID_USER, null);
			}
		}else{
			//302登陆成功，什么也不需要返回
		}
	}

	@Override
	public void signOut() throws ApiException, IOException {
		
	}

	@Override
	public byte[] retireCpatcha() throws ApiException, IOException {
		HttpRequest req = createHttpRequest(String.format(URL_CAPTCHA, Math.random()), "GET");
		HttpResponse res = executeHttpRequest(req);
		return res.getResponseData();
	}

	@Override
	public FriendList retireMyFriends(String index) throws ApiException, IOException {
		FriendList friendList = new FriendList();
		friendList.setHasGroup(true);
		friendList.setHasNext(false);
		friendList.setNextIndex(null);
		
		//首先获取分组列表
		HttpRequest req = createHttpRequest(URL_GROUPS, "POST");
		req.addPostValue("bgid", "0");
		HttpResponse res = executeHttpRequest(req);
		String body = res.getResponseString();
		
		Pattern pt = Pattern.compile(REGXP_GROUP);
		Matcher mc = pt.matcher(body);
		while(mc.find()){
			friendList.getGroups().add(new Group(mc.group(1), mc.group(2)));
		}
		
		//获取好友列表
		req = createHttpRequest(URL_FRIENDS, "POST");
		req.addPostValue("BGId", "0");
		res = executeHttpRequest(req);
		body = res.getResponseString();
		try {
			JSONArray result = new JSONArray(body);
			for(int i=0; i<result.length(); i++){
				JSONObject json = result.getJSONObject(i);
				Friend friend = new Friend();
				friend.setFid(json.optString("UserId"));
				friend.setGid(json.optString("BuddyGroups"));
				friend.setName(json.optString("LocalName"));
				
				friendList.getFriends().add(friend);
			}
		} catch (JSONException e) {
			throw new ApiException(ErrorCode.INVALID_RESPONSE, e);
		}
		
		return friendList;
	}

	@Override
	public FriendList retireMayKnowns(String index) throws ApiException,
			IOException {
		FriendList friendList = new FriendList();
		HttpRequest req = createHttpRequest(URL_MAYKNOWNS, "POST");
		HttpResponse res = executeHttpRequest(req);
		String body = res.getResponseString();
		
		try {
			JSONArray result = new JSONArray(body);
			for(int i=0; i<result.length(); i++){
				JSONObject json = result.getJSONObject(i);
				Friend friend = new Friend();
				friend.setFid(json.optString("UserId"));
				friend.setGid("");
				friend.setName(json.optString("NickName"));
				
				friendList.getFriends().add(friend);
			}
		} catch (JSONException e) {
			throw new ApiException(ErrorCode.INVALID_RESPONSE, e);
		}
		
		friendList.setHasNext(false);	//飞信只需一次请求就可以获取完毕
		return friendList;
	
	}

	@Override
	public Avatar retireFriendAvatar(Friend friend, Scale scale)
			throws ApiException, IOException {
		HttpRequest req = createHttpRequest(String.format(URL_FRIEND_AVATAR, friend.getFid(), scale==Scale.LARGE?"120":"64"), "GET");
		HttpResponse res = executeHttpRequest(req);
		if(res.getResponseCode()==HttpURLConnection.HTTP_OK){
			Avatar avatar = friend.getAvatar();
			avatar.setData(res.getResponseData());
			avatar.setUrl(req.getUrl());
			return avatar;
		}else if(res.getResponseCode()==HttpURLConnection.HTTP_MOVED_TEMP){
			throw new ApiException(ErrorCode.NO_AVATAR, null);
		}else{
			throw new ApiException(ErrorCode.INVALID_RESPONSE, null);
		}
	}

	@Override
	public Avatar retireMyAvatar(Friend friend, Scale scale) throws ApiException,
			IOException {
		HttpRequest req = createHttpRequest(URL_MY_AVATAR, "GET");
		HttpResponse res = executeHttpRequest(req);
		if(res.getResponseCode()==HttpURLConnection.HTTP_OK){
			Avatar avatar = friend.getAvatar();
			avatar.setData(res.getResponseData());
			avatar.setUrl(req.getUrl());
			return avatar;
		}else if(res.getResponseCode()==HttpURLConnection.HTTP_MOVED_TEMP){
			throw new ApiException(ErrorCode.NO_AVATAR, null);
		}else{
			throw new ApiException(ErrorCode.INVALID_RESPONSE, null);
		}
	}
	@Override
	public Friend retireMyInfo() throws ApiException, IOException {
		HttpRequest req = createHttpRequest(URL_MY_INFO, "GET");
		HttpResponse res = executeHttpRequest(req);
		if(res.getResponseCode()==HttpResponse.HTTP_OK){
			Friend my = new Friend();
			String body = res.getResponseString();
			Pattern pt = Pattern.compile(PT_MY_ID);
			Matcher mc = pt.matcher(body);
			if(mc.find()) my.setFid(mc.group(1));
			
			pt = Pattern.compile(PT_MY_NICK);
			mc = pt.matcher(body);
			if(mc.find()) my.setNick(mc.group(1));
			return my;
		}else{
			throw new ApiException(ErrorCode.INVALID_RESPONSE, null);
		}
	}
}
